﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Commons.Configuration;

namespace SPMS.Log.Configuration.Handler
{
    /// <summary>
    /// 日志记录器节点解析器
    /// </summary>
    /// <remarks>用于解析日志记录器节点</remarks>
    /// <history>
    /// [zanezeng]               2009/10/15 14:49    创建
    /// </history>
    public sealed class Logger_NodeHandler : AbstractNodeHandler
    {
        /// <summary>
        /// 处理指定的节点
        /// </summary>
        /// <param name="node">配置节点</param>
        /// <param name="context">处理上下文</param>
        /// <returns>根据配置信息创建的对象</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 11:39    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 14:49    创建
        /// </history>
        protected override object ProcessInternal( IConfigurationNode node, ParseContext context )
        {
            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace( "开始解析日志记录器" );
            }

            //获得日志记录器的名称
            string loggerName = this.GetAttributeValue( node, LogConfiguationTags.ATTRIBUTE_NAME, context );

            //判断是否指定了追加器的名称
            if (string.IsNullOrEmpty( loggerName ))
            {
                //抛出异常
                throw new ConfigurationException( string.Format( Properties.Resources.MSG_CONFIGURATION_ATTRIBUTE_REQUIRED, node.Name, LogConfiguationTags.ATTRIBUTE_NAME ), node );
            }

            //用于保存日志级别
            Level loggerLevel = context.Repository.DefaultLevel;

            //读取日志级别名称
            string levelName = this.GetAttributeValue( node, LogConfiguationTags.ATTRIBUTE_LEVEL, context );

            //判断是否设置了默认的日志级别
            if (!string.IsNullOrEmpty( levelName ))
            {
                //设置默认的日志级别
                loggerLevel = context.Repository.LevelMap.LookupLevelWithDefault( levelName, context.Repository.DefaultLevel );
            }

            //用于保存配置节点处理器
            IConfigurationNodeHandler<ParseContext> handler;

            //用于保存处理的结果
            object instance = null;

            //用于记录引用的日志记录器名称
            List<string> appenderNames = new List<string>();

            //循环当前配置节点的所有子节点
            foreach (IConfigurationNode subNode in node.ChildNodes)
            {
                //获得配置节点处理器
                handler = context.GetNodeHandler( subNode );

                //判断是否为Null
                if (null == handler)
                {
                    //抛出异常
                    throw new NotSupportedException( string.Format( Properties.Resources.MSG_TAG_NOTSUPPORTED, subNode.Name ) );
                }

                //处理节点
                instance = handler.Porcess( subNode, context );

                //判断是否为日志追加器引用节点
                if (subNode.Name == LogConfiguationTags.TAG_APPENDER_REF)
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace( "开始解析日志记录器'{0}'的引用追加器'{1}'", loggerName, instance );
                    }

                    //记录引用的日志记录器
                    appenderNames.Add( (string)instance );

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace( "日志记录器'{0}'的引用追加器'{1}'解析完毕", loggerName, instance );
                    }
                }
            }

            //注册日志记录器
            context.Repository.RegisterLogger( loggerName, loggerLevel, false, appenderNames.ToArray() );

            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace( "日志记录器'{0}'解析完毕", loggerName );
            }

            //返回日志记录器的名称
            return loggerName;
        }
    }
}
